/*                                                                              
 * SPI testing utility (using spidev driver)                                    
 *                                                                              
 * Copyright (c) 2007  MontaVista Software, Inc.                                
 * Copyright (c) 2007  Anton Vorontsov <avorontsov@ru.mvista.com>               
 *                                                                              
 * This program is free software; you can redistribute it and/or modify         
 * it under the terms of the GNU General Public License as published by         
 * the Free Software Foundation; either version 2 of the License.               
 *                                                                              
 * Cross-compile with cross-gcc -I/path/to/cross-kernel/include                 
 */                                                                             
 

/*
	$ gcc -o spidev_test spidev_test.c
	odroid@odroid:~$ ./spidev_test
	spi mode: 0
	bits per word: 8
	max speed: 500000 Hz (500 KHz)
	 
	34 34 34 34
	If you tie the MOSI and MISO pins, the output is “AB 00 00 00”.
	We call it loopback test.
*/


#include <stdint.h>                                                             
#include <stdio.h>                                                              
#include <stdlib.h>   
#include <string.h>
#include <fcntl.h>      
#include <unistd.h>
#include <getopt.h>
#include <sys/ioctl.h>                                                          
#include <linux/spi/spidev.h>   
#include <linux/types.h>

 
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))                              
 
static void pabort(const char *s)                                               
{                                                                               
        perror(s);                                                              
        abort();                                                                
}                                                                               
 
static const char *device = "/dev/spidev6.0";                                   
static uint8_t mode;                                                            
static uint8_t bits = 8;                                                        
static uint32_t speed = 500000;                                                 
 
static void transfer(int fd)                                                    
{                                                                               
        int ret;                                                                
        uint8_t tx[] = {                                                        
                0xAB, 0x00, 0x00, 0x00                                          
        };                                                                      
        uint8_t rx[ARRAY_SIZE(tx)] = {0, };                                     
 
        struct spi_ioc_transfer tr[2];                                          
        tr[0].tx_buf = (unsigned long)tx;
        tr[0].rx_buf = (unsigned long)rx;                                       
        tr[0].len = ARRAY_SIZE(tx);                                             
        tr[0].speed_hz = speed;                                                 
        tr[0].bits_per_word = bits;                                             
        tr[0].delay_usecs = 0;
        tr[0].cs_change = 0;
 
        tr[1].tx_buf = (unsigned long)tx;                                                                        
        tr[1].rx_buf = (unsigned long)rx;                                       
        tr[1].len = ARRAY_SIZE(tx);                                             
        tr[1].speed_hz = speed;                                                 
        tr[1].bits_per_word = bits;                                             
        tr[1].delay_usecs = 0;
        tr[1].cs_change = 0;                                                                        
 
        ret = ioctl(fd, SPI_IOC_MESSAGE(2), tr);                                
        if (ret < 1)                                                            
                pabort("can't send spi message");                               
 
        for (ret = 0; ret < ARRAY_SIZE(tx); ret++) {                            
                if (!(ret % 6))                                                 
                        puts("");                                               
                printf("%.2X ", rx[ret]);                                       
        }                                                                       
        puts("");                                                               
}                                                                               
 
int main(void)                                                                  
{                                                                               
        int ret = 0;                                                            
        int fd;                                                                 
 
        fd = open(device, O_RDWR);                                              
        if (fd < 0)                                                             
                pabort("can't open device");                                    
 
        /*                                                                      
         * spi mode                                                             
         */                                                                     
        ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);                                
        if (ret == -1)                                                          
                pabort("can't set spi mode");                                   
 
        ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);                                
        if (ret == -1)                                                          
                pabort("can't get spi mode");                                   
 
        /*                                                                      
         * bits per word                                                        
         */                                                                     
        ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);                       
        if (ret == -1)                                                          
                pabort("can't set bits per word");                              
 
        ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);                       
        if (ret == -1)                                                          
                pabort("can't get bits per word");                              
 
        /*                                                                      
         * max speed hz                                                         
         */                                                                     
        ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);                       
        if (ret == -1)                                                          
                pabort("can't set max speed hz");                               
 
        ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);                       
        if (ret == -1)                                                          
                pabort("can't get max speed hz");                               
 
        printf("spi mode: %d\n", mode);                                         
        printf("bits per word: %d\n", bits);                                    
        printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);               
 
        transfer(fd);                                                           
 
        close(fd);                                                              
 
        return ret;                                                             
}
